package com.orientation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orientation.commom.exception.CustomException;
import com.orientation.dto.BatchBedDto;
import com.orientation.dto.BedChangeDto;
import com.orientation.dto.BedStudentDto;
import com.orientation.entity.Class;
import com.orientation.entity.*;
import com.orientation.mapper.*;
import com.orientation.service.BedService;
import com.orientation.service.BuildingService;
import com.orientation.service.RoomService;
import com.orientation.service.StudentService;
import com.orientation.utils.BeanConvertUtils;
import com.orientation.utils.PageUtils;
import com.orientation.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 报到 服务实现类
 * </p>
 *
 * @author xuandian
 * @since 2022-3-9
 */
@Service
public class BedServiceImpl extends ServiceImpl<BedMapper, Bed> implements BedService {
    @Resource
    private StudentService studentService;
    @Resource
    private BedService bedService;
    @Resource
    private BedMapper bedMapper;
    @Resource
    private RoomService roomService;
    @Resource
    private RoomMapper roomMapper;
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private MajorMapper majorMapper;
    @Resource
    private CollegeMapper collegeMapper;
    @Resource
    private ClassMapper classMapper;
    @Resource
    private BuildingService buildingService;
    @Resource
    private FilesService filesService;

    @Override
    public StudentProgressVo progressBed(String collegeId) {
        StudentProgressVo studentProgressVo = new StudentProgressVo();
        List<Student> students = studentService.list(Wrappers.<Student>lambdaQuery().eq(StringUtils.hasLength(collegeId), Student::getCollegeId, collegeId));
        if (!CollectionUtils.isEmpty(students)) {
            //报道表存在学生信息
            List<String> list = students.stream().map(Student::getStudentId).distinct().collect(Collectors.toList());
            //报道表存在学生信息
            // List<Bed> bedList = bedMapper.selectList(new LambdaQueryWrapper<Bed>().isNotNull(true, Bed::getStudentId));
            List<Bed> bedList = bedMapper.selectList(new LambdaQueryWrapper<Bed>().in(!CollectionUtils.isEmpty(list), Bed::getStudentId, list));
            studentProgressVo.setStudentNum(students.size());
            studentProgressVo.setNotNum(students.size() - bedList.size());
            if (!CollectionUtils.isEmpty(bedList)) {
                //过滤已经报道的情况 filter 满足tioajian的数据
                studentProgressVo.setReserveNum(bedList.size());

                if (students.size() > 0) {
                    BigDecimal installRate = new BigDecimal(bedList.size()).multiply(new BigDecimal("100")).divide(new BigDecimal(students.size()), 2, BigDecimal.ROUND_HALF_UP);
                    studentProgressVo.setFinishProgress(installRate);
                }
            } else {

                studentProgressVo.setReserveNum(0);
                studentProgressVo.setFinishProgress(new BigDecimal("00"));
            }
        }

        return studentProgressVo;
    }

    @Override
    public void insertBed(Bed bed) {
        if (!StringUtils.hasLength(bed.getRoomId())) {
            throw new CustomException("18", "房间信息必填");
        } else {
            Room room = roomService.getOne(Wrappers.<Room>lambdaQuery().eq(StringUtils.hasLength(bed.getRoomId()), Room::getSid, bed.getRoomId()));
            if (room == null) {
                throw new CustomException("18", "房间信息填写错误");
            } else {
                Bed one = bedMapper.selectOne(new LambdaQueryWrapper<Bed>().eq(Bed::getName, bed.getName()));
                if (one != null) {
                    throw new CustomException("18", "此房间已经存在");
                } else {
                    save(bed);
                    room.setBed(room.getBed() == null ? 1 : room.getBed() + 1);
                    roomService.updateById(room);
                }
            }
        }
    }

    @Override
    public void insertBedBatch(List<Bed> bedList) {
        if (!CollectionUtils.isEmpty(bedList)) {
            for (Bed b : bedList) {
                if (!StringUtils.hasLength(b.getRoomId())) {
                    throw new CustomException("18", "房间信息必填");
                }
            }
            Room room = roomService.getOne(Wrappers.<Room>lambdaQuery().eq(StringUtils.hasLength(bedList.get(0).getRoomId()), Room::getSid, bedList.get(0).getRoomId()));
            if (org.apache.commons.lang3.ObjectUtils.isEmpty(room)) {
                throw new CustomException("18", "房间信息填写错误");
            }
            if (room.getBed() != null) {
                if (room.getBed() >= 4) {
                    throw new CustomException("18", "最多只能添加四个床位");
                }
                room.setBed(room.getBed() + bedList.size());
            } else {
                room.setBed(bedList.size());
            }
            //文件上传
            // if (files != null && files.length > 0) {
            //     List<String> stringUrls = filesService.getStringUrls(files);
            //     if (!CollectionUtils.isEmpty(stringUrls)) {
            //         room.setRoomurl(stringUrls == null ? null : org.apache.commons.lang3.StringUtils.join(stringUrls, ","));
            //     }
            // }
            roomService.updateById(room);
            List<String> bedNames = bedList.stream().map(Bed::getName).collect(Collectors.toList());
            List<Bed> beds = bedService.list(Wrappers.<Bed>lambdaQuery().in(Bed::getName, bedNames).eq(StringUtils.hasLength(bedList.get(0).getRoomId()), Bed::getRoomId, bedList.get(0).getRoomId()));
            if (CollectionUtils.isEmpty(beds)) {
                saveBatch(bedList);

            } else {
                throw new CustomException("18", "房间已经存在");
            }
        } else {
            throw new CustomException("18", "添加内容为空");
        }
    }

    @Override
    public BedStudentVo queryBed(String bedId) {
        BedStudentVo result = new BedStudentVo();
        Bed bed = bedMapper.selectById(bedId);
        Room  room=roomMapper.selectById(bed.getRoomId());
        Building building=buildingService.getById(room.getBuildingId());
        result.setRoomName(room.getName());
        result.setBuildingName(building.getName());
        result.setFloorNum(building.getFloor());
        if (bed != null) {
            Student student = studentMapper.selectOne(new LambdaQueryWrapper<Student>().eq(Student::getStudentId, bed.getStudentId()));
            if (student != null) {
                Major major = majorMapper.selectOne(new LambdaQueryWrapper<Major>().eq(Major::getSid, student.getMajorId()).eq(Major::getCollegeId, student.getCollegeId()));
                College college = collegeMapper.selectOne(new LambdaQueryWrapper<College>().eq(College::getSid, student.getCollegeId()));
                Class aClass = classMapper.selectOne(new LambdaQueryWrapper<Class>().eq(Class::getSid, student.getClassId()));
                result.setStudentName(student.getStudentName());
                result.setCollegeName(college.getCollegeName());
                result.setClassName(aClass.getClassName());
                result.setMajorName(major.getMajorName());
                result.setBedName(bed.getName());
            }
        }

        return result;
    }

    @Override
    public List<BedStudentVo> queryBedStudentList(String roomId) {
        List<BedStudentVo> result = new ArrayList<>();
        List<Bed> beds = bedService.list(Wrappers.<Bed>lambdaQuery().eq(Bed::getRoomId, roomId));
        if (!CollectionUtils.isEmpty(beds)) {
            List<Bed> pileStageList = beds.stream().filter((Bed bed) -> StringUtils.hasLength(bed.getStudentId())).collect(Collectors.toList());
            List<String> studentIds = pileStageList.stream().map(Bed::getStudentId).collect(Collectors.toList());
            List<Student> students = studentService.list(Wrappers.<Student>lambdaQuery().in(!CollectionUtils.isEmpty(studentIds), Student::getStudentId, studentIds));
            List<String> collegeIds = students.stream().map(Student::getCollegeId).collect(Collectors.toList());
            List<String> majorIds = students.stream().map(Student::getMajorId).collect(Collectors.toList());
            List<String> classIds = students.stream().map(Student::getClassId).collect(Collectors.toList());
            List<Major> majors = majorMapper.selectList(new LambdaQueryWrapper<Major>().in(!CollectionUtils.isEmpty(majorIds), Major::getSid, majorIds));
            List<Class> classes = classMapper.selectList(new LambdaQueryWrapper<Class>().in(!CollectionUtils.isEmpty(classIds), Class::getSid, classIds));
            List<College> colleges = collegeMapper.selectList(new LambdaQueryWrapper<College>().in(!CollectionUtils.isEmpty(collegeIds), College::getSid, collegeIds));
            for (Bed bed : beds) {
                //todo 待处理数据
                BedStudentVo vo = new BedStudentVo();
                if (StringUtils.hasLength(bed.getStudentId())) {
                    for (Student student : students) {
                        if (student.getStudentId().equals(bed.getStudentId())) {
                            vo.setStudentName(student.getStudentName());
                        }
                        for (College college : colleges) {
                            if (StringUtils.hasLength(student.getCollegeId()) && college.getSid().equals(student.getCollegeId())) {
                                vo.setCollegeName(college.getCollegeName());
                            }
                        }
                        for (Major major : majors) {
                            if (StringUtils.hasLength(student.getMajorId()) && major.getSid().equals(student.getMajorId())) {
                                vo.setMajorName(major.getMajorName());
                            }
                        }
                        for (Class clazz : classes) {
                            if (StringUtils.hasLength(student.getClassId()) && clazz.getSid().equals(student.getClassId())) {
                                vo.setClassName(clazz.getClassName());
                            }
                        }
//                        if (StringUtils.hasLength(bed.getStudentId()) && bed.getStudentId().equals(student.getStudentId())) {
//                            vo.setBedName(bed.getName());
//                        }
                    }
                }
                vo.setBedName(bed.getName());
                result.add(vo);
            }
        }
        return result;
    }

    @Override
    public void distributionBed(BatchBedDto batchBedDto) {
        if (!CollectionUtils.isEmpty(batchBedDto.getStudentId())) {
            // List<Bed> beds = bedService.list(Wrappers.<Bed>lambdaQuery().in(Bed::getStudentId, batchBedDto.getStudentId()));
            // if (!CollectionUtils.isEmpty(beds) ) {
            //     throw
            // }
            List<BedStudentDto> values = new ArrayList<>();
            for (int i = 0; i < batchBedDto.getStudentId().size(); i++) {
                BedStudentDto bedStudentDto = new BedStudentDto();
                bedStudentDto.setStudentId(batchBedDto.getStudentId().get(i));
                values.add(bedStudentDto);
            }
            batchBedDto.setBedStudentList(values);
        }
        if (batchBedDto != null && StringUtils.hasLength(batchBedDto.getBuildingId()) && !CollectionUtils.isEmpty(batchBedDto.getBedStudentList())) {
            List<Room> rooms = roomService.list(Wrappers.<Room>lambdaQuery().eq(StringUtils.hasLength(batchBedDto.getBuildingId()), Room::getBuildingId, batchBedDto.getBuildingId()));
            if (!CollectionUtils.isEmpty(rooms)) {
                List<String> roomIds = rooms.stream().map(Room::getSid).distinct().collect(Collectors.toList());
                List<Bed> bedList = bedService.list(Wrappers.<Bed>lambdaQuery().in(!CollectionUtils.isEmpty(roomIds), Bed::getRoomId, roomIds).isNull(Bed::getStudentId));
                //先房间//再床位 //排序
                bedList = bedList.stream().sorted(Comparator.comparing(Bed::getRoomId).thenComparing(Comparator.comparing(Bed::getName))).collect(Collectors.toList());
                if (bedList.size() == 0) {
                    throw new CustomException("15", "请先维护床位信息");
                }
                if (!CollectionUtils.isEmpty(bedList) && batchBedDto.getBedStudentList().size() > bedList.size()) {
                    throw new CustomException("应该少选学生人数" + String.valueOf(batchBedDto.getBedStudentList().size() - bedList.size()), "当前学生人数量超过该楼层最多限制人数");
                } else if (!CollectionUtils.isEmpty(bedList) && batchBedDto.getBedStudentList().size() <= bedList.size()) {
                    bedList = bedList.subList(0, batchBedDto.getBedStudentList().size());
                    for (int i = 0; i < bedList.size(); i++) {
                        bedList.get(i).setStudentId(batchBedDto.getBedStudentList().get(i).getStudentId());
                    }
                    updateBatchById(bedList);
                }
            } else {
                throw new CustomException("15", "请先维护房间信息");
            }
        } else {
            throw new CustomException("15", "房间信息必填和学生信息必填");
        }
    }

    @Override
    public BedRoomStudentVo queryByStudentId(String studentId) {
        BedRoomStudentVo bedRoomStudentVo = new BedRoomStudentVo();
        Bed bed = bedService.getOne(Wrappers.<Bed>lambdaQuery().eq(Bed::getStudentId, studentId));
        if (!ObjectUtils.isEmpty(bed)) {
            Room room = roomService.getById(bed.getRoomId());
            Building building = buildingService.getOne(Wrappers.<Building>lambdaQuery()
                    .eq(StringUtils.hasLength(room.getBuildingId()), Building::getSid, room.getBuildingId())
                    .eq(StringUtils.hasLength(room.getFloor()), Building::getFloor, room.getFloor()));
            BeanUtils.copyProperties(building, bedRoomStudentVo);
            bedRoomStudentVo.setStudentId(bed.getStudentId());
            bedRoomStudentVo.setBedName(bed.getName());
            bedRoomStudentVo.setRoomName(room.getName());
            bedRoomStudentVo.setRoomurl(room.getRoomurl());
        }
        return bedRoomStudentVo;
    }

    @Override
    public void insertBedBatchFile(MultipartFile[] files, List<String> names, String roomId) {
        List<Bed> beds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(names) && StringUtils.hasLength(roomId)) {
            for (String name : names) {
                Bed bed = new Bed();
                bed.setRoomId(roomId);
                bed.setName(name);
                beds.add(bed);
            }
            List<Bed> bedList = bedService.list(Wrappers.<Bed>lambdaQuery().in(Bed::getName, names).eq(StringUtils.hasLength(roomId), Bed::getRoomId, roomId));
            if (CollectionUtils.isEmpty(bedList)) {
                this.saveBatch(beds);
            } else {
                throw new CustomException("18", "床位已经存在");
            }
        }
        Room room = roomService.getOne(Wrappers.<Room>lambdaQuery().eq(StringUtils.hasLength(roomId), Room::getSid, roomId));
        if (org.apache.commons.lang3.ObjectUtils.isEmpty(room)) {
            throw new CustomException("18", "房间信息填写错误");
        }
        if (room.getBed() != null) {
            if (room.getBed() >= 4 && !CollectionUtils.isEmpty(names)) {
                throw new CustomException("18", "最多只能添加四个床位");
            }
            room.setBed(room.getBed() + beds.size());
        } else {
            room.setBed(beds.size());
        }
        //文件上传
        if (files != null && files.length > 0) {
            List<String> stringUrls = filesService.getStringUrls(files);
            if (!CollectionUtils.isEmpty(stringUrls)) {
                room.setRoomurl(stringUrls == null ? null : org.apache.commons.lang3.StringUtils.join(stringUrls, ","));
            }
        }
        roomService.updateById(room);
    }

    @Override
    public IPage<BedMoveVo> queryBedMove(Integer pageNum, Integer pageSize, String majorId, String className, String studentName, String studentId, String sexType, String adviserId) {
        List<StudentClassInfoVo> studentClassInfoVos = studentService.getStudentClassInfoVos(null, majorId, className, studentName, null, "1", studentId);
        if (CollectionUtils.isEmpty(studentClassInfoVos)) {
            throw new CustomException("18", "暂无信息");
        }
        if (!StringUtils.hasLength(adviserId)) {
            throw new CustomException("18", "adviserId必须填写");
        }
        List<StudentClassInfoVo> studentClassVoList = studentClassInfoVos.stream().filter((StudentClassInfoVo s) -> s.getAdviserId().equals(adviserId)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(studentClassVoList)) {
            throw new CustomException("18", "只能查看自己所在专业学生信息");
        }
        List<String> studentIds = studentClassInfoVos.stream().map(StudentClassInfoVo::getStudentId).distinct().collect(toList());
        //获取已经分床位学生学号
        List<Bed> bedList = bedService.list(Wrappers.<Bed>lambdaQuery().in(!CollectionUtils.isEmpty(studentIds), Bed::getStudentId, studentIds));

        //两个对象根据学生id 取交集
        List<StudentClassInfoVo> studentInfoVoList = studentClassInfoVos.stream().filter(
                m -> bedList.stream().map(Bed::getStudentId).collect(toList()).contains(m.getStudentId())).collect(toList());
        if (!StringUtils.hasLength(sexType)) {
            throw new CustomException("18", "男女类类型必须选择");
        }
        List<StudentClassInfoVo> studentClassInfoVoList = new ArrayList<>();

        //1 男生2 女生
        if ("1".equals(sexType)) {
            studentClassInfoVoList = studentInfoVoList.stream().filter((StudentClassInfoVo vo) -> StringUtils.hasLength(vo.getGender()) && "男".equals(vo.getGender())).collect(toList());
        } else {
            studentClassInfoVoList = studentInfoVoList.stream().filter((StudentClassInfoVo vo) -> StringUtils.hasLength(vo.getGender()) && "女".equals(vo.getGender())).collect(toList());
        }
        List<BedMoveVo> bedMoveVos = BeanConvertUtils.copyListProperties(studentClassInfoVoList, BedMoveVo::new);
        for (BedMoveVo bedMoveVo : bedMoveVos) {
            for (Bed bed : bedList) {
                if (bed.getStudentId().equals(bedMoveVo.getStudentId())) {
                    Room room = roomService.getOne(Wrappers.<Room>lambdaQuery().eq(Room::getSid, bed.getRoomId()).groupBy(Room::getSid));
                    Building building = buildingService.getById(room.getBuildingId());
                    bedMoveVo.setBedSid(bed.getSid());
                    bedMoveVo.setBedName(bed.getName());
                    bedMoveVo.setRoomurl(room.getRoomurl());
                    bedMoveVo.setRoomName(room.getName());
                    bedMoveVo.setBuildingName(building.getName());
                    bedMoveVo.setFloor(building.getFloor());
                    bedMoveVo.setRegion(building.getRegion());
                    bedMoveVo.setType(building.getType());
                }
            }
        }
        return PageUtils.getPage(bedMoveVos, pageNum, pageSize);
    }

    @Override
    public void distributionChangeBed(BedChangeDto bedChangeDto) {
        if (!ObjectUtils.isEmpty(bedChangeDto) && bedChangeDto.getStudentIds().size() == 2 && bedChangeDto.getStudentIds().get(0)!=bedChangeDto.getStudentIds().get(1)) {

            List<Bed> beds = bedService.list(Wrappers.<Bed>lambdaQuery().in(Bed::getStudentId, bedChangeDto.getStudentIds()));
            String st = beds.get(0).getStudentId();
            beds.get(0).setStudentId(beds.get(1).getStudentId());
            beds.get(1).setStudentId(st);
            this.updateBatchById(beds);
        } else {
            throw new CustomException("18", "交换信息填写错误");
        }
    }

}
